package com.edu.spring.aop.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 何时？注解
 * 何地？切入点表达式
 * 增强器链：切面中的所有通知方法其实就是增强器。它们被组织成一个链路放到集合中。
 * 目标方法真正执行前后，会去增强器链中执行需要提前执行的方法。
 * AOP的底层原理：
 * 1.Spring会为每个被切面切入的组件创建代理对象，（Spring CGLIB 创建的代理对象，无视接口）
 * 2.代理对象中保存了切面类里面所有通知方法构成的增强器链。
 * 3.目标方法执行时，会先执行增强器链中需要提前执行的通知方法。
 */
@Component
@Aspect
public class LogAspect {
    @Before("execution(int com.edu.spring.aop.impl.MathCalculatorImpl.*(int,int))")
    public void logStart(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        String name = signature.getName();
//        System.out.println("【切面 - 日志】开始执行..." + name);
        String string = signature.getMethod().toString();
        System.out.println("【切面 - 日志】开始..." + string);
        System.out.println("【切面 - 日志】开始..." + Arrays.toString(joinPoint.getArgs()));
    }

    @After("execution(int com.edu.spring.aop.impl.MathCalculatorImpl.*(int,int))")
    public void logEnd() {

        System.out.println("【切面 - 日志】结束。");
    }

    @AfterReturning(value = "execution(int com.edu.spring.aop.impl.MathCalculatorImpl.*(int,int))",
            returning = "result")
    public void logReturn(Object result) {
        System.out.println("【切面 - 日志】返回... 值为：" + result);
    }

    //    @Before("args(int,int)")
//    @Before("@args(org.aspectj.lang.annotation.AfterThrowing )")
    @AfterThrowing(value = "execution(int com.edu.spring.aop.impl.MathCalculatorImpl.*(int,int))",
            throwing = "e")
    public void logException(Exception e) {
        System.out.println("【切面 - 日志】异常：" + e.getMessage());
    }

}
